#pragma once
#include <string>
#include "XnccAddress.h"
namespace xncc {
namespace foundation {
    class IpV4Address final : public XnccAddress
    {
      public:
        using s_ptr = std::shared_ptr<IpV4Address>;
        explicit IpV4Address(const std::string& addr, int protocol = IPPROTO_TCP);
        explicit IpV4Address(const struct sockaddr_in& addr, int protocol = IPPROTO_TCP);
        explicit IpV4Address(int protocol = IPPROTO_TCP);
        ~IpV4Address() override;

        IpV4Address(const IpV4Address&)             = delete;
        IpV4Address(const IpV4Address&&)            = delete;
        IpV4Address& operator=(const IpV4Address&)  = delete;
        IpV4Address& operator=(const IpV4Address&&) = delete;

        [[nodiscard]] auto Type() const -> shared::XNCC_ADDR_TYPE override
        {
            return protocol_ == IPPROTO_TCP ? shared::XNCC_ADDR_TYPE::IPV4_TCP : shared::XNCC_ADDR_TYPE::IPV4_UDP;
        }
        [[nodiscard]] auto family() const -> sa_family_t override { return addr_.sin_family; }
        [[nodiscard]] auto toStr() const -> std::string override { return toIpPort(); }
        [[nodiscard]] auto getSockAddr() const -> const struct sockaddr* override
        {
            return reinterpret_cast<const struct sockaddr*>(&addr_);
        }
        [[nodiscard]] auto getSockLen() const -> socklen_t override { return static_cast<socklen_t>(sizeof(addr_)); }

        void setSockAddr(const struct sockaddr_in& addr) { addr_ = addr; }

        [[nodiscard]] std::string toIp() const;
        [[nodiscard]] uint16_t    toPort() const;
        [[nodiscard]] std::string toIpPort() const;

      private:
        struct sockaddr_in addr_ = {};
        const int          protocol_;
    };
}  // namespace foundation
}  // namespace xncc